// import { Server } from 'http';

type loggerFunctionType = (message: string) => void;

/**
 * 用于与前端页面内容读取端交互的WebSocket服务端
 */
export class SocketServer {
    io: SocketIO.Server;
    sockets: SocketIO.Socket[] = [];
    logger: loggerFunctionType;
    port: string;

    static instance: SocketServer;

    private constructor(log: loggerFunctionType, port: string) {
        this.logger = log;
        this.port = port;
        this.sockets = [];
    }

    static getInstance(log: loggerFunctionType, port: string) {
        if (SocketServer.instance === undefined) {
            SocketServer.instance = new SocketServer(log, port);
        }

        return SocketServer.instance;
    }

    start = () => {
        if (this.io === undefined) {
            // const httpServer = new Server((req, res) => {
            //     res.setHeader('Access-Control-Allow-Origin', '*:*');
            //     res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With');
            //     res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
            //     res.setHeader('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
            // });
            this.io = require('socket.io').listen(this.port);
            this.io.origins('*:*');
            this.io.sockets.on('connection', this.onConnect);
            this.io.sockets.on('error', this.onError);
            this.logger('push webSocket service start, listening on port ' + this.port);
        }
    }

    onNews = (data) => {
        this.emitMessageToAll('updater', data);
    }

    onConnect = (socket: SocketIO.Socket) => {
        this.sockets.push(socket);
        this.logger('new ws (' + socket.id + ') connected, current connections count is ' + this.sockets.length);
        // 回传id
        this.emitMessage(socket, 'register', socket.id);

        socket.on('error', this.onError);
        socket.on('news', this.onNews);
        socket.on('disconnect', () => { this.socketOnDisconnect.call(this, socket); });
    }

    onError = (error: any) => {
        return '';
    }

    prepareMessage = (flag: string, message: string) => {
        return {
            'flag': flag,
            'message': message
        };
    }

    emitMessage = (socket: SocketIO.Socket, flag: string, content: string) => {
        socket.emit('push', JSON.stringify(this.prepareMessage(flag, content)));
    }

    emitMessageToAll = (flag: string, content: string) => {
        this.io.emit('push', JSON.stringify(this.prepareMessage(flag, content)));
    }

    socketOnDisconnect = (socket: SocketIO.Socket) => {
        const index: number = this.sockets.indexOf(socket);
        this.sockets.splice(index, 1);
        this.logger('ws (' + socket.id + ') disconnected, current connections count is ' + this.sockets.length);
    }

    pushHtmlObjToWS = (wsid: string, htmlObj: string) => {
        let selectedSocket = null;
        this.sockets.forEach((socket) => {
            if (socket.id === wsid) {
                selectedSocket = socket;
            }
        });

        if (selectedSocket === null) {
            throw new Error('未能获取到有效的前端页面通道，设计页面可能已经关闭或刷新');
        }

        this.emitMessage(selectedSocket, 'content', htmlObj);
    }
}
